/*
 * main.cpp
 *
 *  Created on: Mar 7, 2012
 *      Author: ajeffery
 */


#include "Comm_Manager.h"
#include "Double_Buffer.h"
#include "Status_Manager.h"
#include "FloorRun_Manager.h"
#include "Supervisor.h"
#include "defs.h"
#include "Elevator.h"

#include <native/task.h>
#include <native/timer.h>
#include <sys/mman.h>
#include <rtdk.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>

RT_TASK comm_task;
RT_TASK status_task;
RT_TASK floor_run_task;
RT_TASK supervisor_task;
RT_TASK gui_comm_manager;

//Global
Elevator *this_lift;

//Local to main.cpp
Comm_Manager *comm;
Double_Buffer *dbuffer;
FloorRun_Manager *flr_run;
Status_Manager *status_mnger;
Supervisor *supervsr;

void comm_run(void* arg){
	comm->readSocket();
}

void gui_comm_run(void* arg){
	status_mnger->read_floor_request();
}

void status_run(void* arg){
	rt_task_set_periodic(NULL, TM_NOW, STATUS_UPDATE_PERIOD);
	while(1){
		rt_task_wait_period(NULL);
		status_mnger->update();
	}

}

void floor_run(void* arg){
	flr_run->operate();
}

void supervisor_run(void* arg){

	while(1){
		rt_task_sleep(rt_timer_ns2ticks(3000000));
	}


}

void create_objects(int arg=0){
	//Local main.cpp
	//Global
	dbuffer= new Double_Buffer();
	this_lift = new Elevator(arg);


	supervsr = new Supervisor();
	flr_run = new FloorRun_Manager();
	status_mnger = new Status_Manager(dbuffer);
	comm = new Comm_Manager(dbuffer);
}

void delete_objects(){
	//Local main.cpp
	delete(supervsr);
	delete(flr_run);
	delete(status_mnger);
	delete(comm);
	delete(dbuffer);

	//Global
	delete(this_lift);
}

void catch_signal(int sig)
{
	rt_printf("\n Signal Caught, Exiting... \n");

	rt_task_delete(&comm_task);
	rt_task_delete(&status_task);
	rt_task_delete(&floor_run_task);
	rt_task_delete(&supervisor_task);
	rt_task_delete(&gui_comm_manager);


	delete_objects();

	rt_printf("Exited. \n");
	exit(0);
}

int main(int argc, char* argv[]){

	rt_print_auto_init(1);
	mlockall(MCL_CURRENT | MCL_FUTURE);

	if (argc == 2) {
		create_objects(atoi(argv[1]));
	} else {
		create_objects();
	}

	//printf("WARNING signal are not enabled");
	signal(SIGTERM, catch_signal);
	signal(SIGINT, catch_signal);

	//Create Tasks
	rt_task_create(&comm_task, 0, 0 , 99, T_JOINABLE);
	rt_task_create(&status_task, 0, 0 , 99, T_JOINABLE);
	rt_task_create(&floor_run_task, 0, 0 , 99, T_JOINABLE);
	rt_task_create(&supervisor_task, 0, 0 , 99, T_JOINABLE);
	rt_task_create(&gui_comm_manager, 0, 0 , 99, T_JOINABLE);

	//Run Tasks
	rt_task_start(&comm_task, &comm_run, 0);
	rt_task_start(&status_task, &status_run, 0);
	rt_task_start(&floor_run_task, &floor_run, 0);
	rt_task_start(&supervisor_task, &supervisor_run, 0);
	rt_task_start(&gui_comm_manager, &gui_comm_run, 0);

	//Wait for all to finish and Join
	rt_task_join(&comm_task);
	rt_task_join(&status_task);
	rt_task_join(&floor_run_task);
	rt_task_join(&supervisor_task);
	rt_task_join(&gui_comm_manager);

	//Clean up Tasks
	rt_task_delete(&comm_task);
	rt_task_delete(&status_task);
	rt_task_delete(&floor_run_task);
	rt_task_delete(&supervisor_task);
	rt_task_delete(&gui_comm_manager);

	delete_objects();

	return 1;
}
